#include "MySPI.h"


//硬件SPI测试程序   V1.1           修改日期：2025/6/12
//实现功能：SPI0做主机，SPI1做从机 交换数据
//By:TAO XIN YU (陶鑫宇)

unsigned char spi0_send_buffer[buffer_size]={0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA};
unsigned char spi1_send_buffer[buffer_size]={0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA};
unsigned char spi0_receive_buffer[buffer_size]={0};
unsigned char spi1_receive_buffer[buffer_size]={0};
																						 

void MySPI_init(void)
{
	
	//开启引脚及其SPI外设时钟
	rcu_periph_clock_enable(RCU_GPIOA);
	rcu_periph_clock_enable(RCU_GPIOB);
	rcu_periph_clock_enable(RCU_SPI0);
	rcu_periph_clock_enable(RCU_SPI1);
	rcu_periph_clock_enable(RCU_DMA);

	
	//SPI0 GPIO模式设置 复用浮空
	gpio_mode_set(GPIOA,GPIO_MODE_AF,GPIO_PUPD_NONE,
								SPI_0_SCK_PIN | SPI_0_MOSI_PIN | 
								SPI_0_MIS0_PIN);
	//SPI0 复用设置 复用为SPI0
	gpio_af_set(GPIOA,GPIO_AF_0,
							SPI_0_SCK_PIN | SPI_0_MOSI_PIN | 
							SPI_0_MIS0_PIN);
	//SPI 输出设置 推挽输出 50MHz
	gpio_output_options_set(GPIOA,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,
													SPI_0_SCK_PIN | SPI_0_MOSI_PIN | 
													SPI_0_MIS0_PIN);
	
	//声明DMA初始化结构体
	dma_parameter_struct dma_init_struct={0};
	//恢复DMA结构体缺省配置
	dma_struct_para_init(&dma_init_struct);
		//恢复DMA通道2缺省配置
	dma_deinit(DMA_CH2);  
	
	//SPI0发送DMA配置
	//配置外设地址
	dma_init_struct.periph_addr = (uint32_t )&SPI_DATA(SPI0);
	//配置存储器地址
	dma_init_struct.memory_addr = (uint32_t)spi0_send_buffer;
	//转运方向 存储器到外设
	dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
	//外设数据宽度 8位
	dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
	//存储器数据宽度 8位
	dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
	//DMA优先级 高优先级
	dma_init_struct.priority = DMA_PRIORITY_HIGH;
	//数据长度
	dma_init_struct.number = buffer_size;
	//外设地址不递增
	dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
	//存储器地址自增
	dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
	//配置DMA通道2
	dma_init(DMA_CH2, &dma_init_struct);
	
	//SPI1发送DMA配置
	dma_deinit(DMA_CH4);
	dma_init_struct.periph_addr = (uint32_t )&SPI_DATA(SPI1);
	dma_init_struct.memory_addr = (uint32_t)spi1_send_buffer;
	dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
	dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH ;
	dma_init(DMA_CH4, &dma_init_struct);
	
	//SPI0接收DMA配置
	dma_deinit(DMA_CH1);
	dma_init_struct.periph_addr = (uint32_t )&SPI_DATA(SPI0);
	dma_init_struct.memory_addr = (uint32_t)spi0_receive_buffer;
	dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
	dma_init_struct.priority = DMA_PRIORITY_LOW;
	dma_init(DMA_CH1, &dma_init_struct);
	
	//SPI1接收DMA配置
	dma_deinit(DMA_CH3);
	dma_init_struct.periph_addr = (uint32_t )&SPI_DATA(SPI1);
	dma_init_struct.memory_addr = (uint32_t)spi1_receive_buffer;
	dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
	dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
	dma_init(DMA_CH3, &dma_init_struct);
	
	
	//SPI1 GPIO模式设置 复用浮空
	gpio_mode_set(GPIOB,GPIO_MODE_AF,GPIO_PUPD_NONE,
								SPI_1_SCK_PIN | SPI_1_MOSI_PIN | 
								SPI_1_MIS0_PIN);
	//SPI1 复用设置 复用为SPI0
	gpio_af_set(GPIOB,GPIO_AF_0,
							SPI_1_SCK_PIN | SPI_1_MOSI_PIN | 
							SPI_1_MIS0_PIN);
	//SPI1 输出设置 推挽输出 50MHz
	gpio_output_options_set(GPIOB,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,
													SPI_1_SCK_PIN | SPI_1_MOSI_PIN | 
													SPI_1_MIS0_PIN);
	
	//声明SPI参数配置结构体
	spi_parameter_struct spi_init_structure={0};
	//恢复SPI外设缺省配置，防止出现意外错误
	spi_i2s_deinit(SPI0);
	spi_i2s_deinit(SPI1);
	spi_struct_para_init(&spi_init_structure);
	
	//配置SPI0
	//传输模式 全双工
	spi_init_structure.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
	//SPI主机模式
	spi_init_structure.device_mode = SPI_MASTER;
	//一帧8位数据
	spi_init_structure.frame_size =SPI_FRAMESIZE_8BIT;
	//SCK空闲时高电平，第二个边沿锁存数据（采样）
	spi_init_structure.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
	//使用软件片选
	spi_init_structure.nss = SPI_NSS_SOFT;
	//时钟8分频 72Mhz / 128 
	spi_init_structure.prescale =SPI_PSC_128;
	//数据传输方向，高位先行
	spi_init_structure.endian = SPI_ENDIAN_MSB;
	//初始化SPI0
	spi_init(SPI0,&spi_init_structure);
	
	//配置SPI1
	//传输模式 全双工 
	spi_init_structure.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
	//SPI从机模式
	spi_init_structure.device_mode = SPI_SLAVE;
	//初始化SPI1
	spi_init(SPI1,&spi_init_structure);
	
	//设置SPI1接收队列缓冲区大小
	spi_fifo_access_size_config(SPI1,SPI_BYTE_ACCESS);
	
	//使能SPI外设
	spi_enable(SPI1);
  spi_enable(SPI0);
	
	//使能各DMA通道
	dma_channel_enable(DMA_CH4);
	dma_channel_enable(DMA_CH2); 
	dma_channel_enable(DMA_CH3);
	dma_channel_enable(DMA_CH1);
	//使能SPI各DMA通道
	spi_dma_enable(SPI1, SPI_DMA_TRANSMIT);
	spi_dma_enable(SPI1, SPI_DMA_RECEIVE);
	spi_dma_enable(SPI0, SPI_DMA_TRANSMIT);
	spi_dma_enable(SPI0, SPI_DMA_RECEIVE);
	
}


